#ifndef AST_NODE_H
#define AST_NODE_H

// #include "Visitor.h"
#include <memory>
#include <list>
#include <vector>
#include "lexer.h"

class Type;

class AstVisitor;
class Var;
class AssignExprNode;

class AstNode {
public:
    std::shared_ptr<Type> Ty;
    std::shared_ptr<Token> Tok;
    virtual ~AstNode() {}
    AstNode(std::shared_ptr<Token> tok) : Tok(tok) {}
    virtual void Accept(AstVisitor *visitor) {}
};  

class ProgramAstNode: public AstNode {
public:
    std::list<std::shared_ptr<AstNode>> Funcs; // 语句链表

    ProgramAstNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class FunctionNode: public AstNode {
public:
    std::string_view FuncName;
    std::list<std::shared_ptr<Var>> Params;   // 函数传入参数
    std::list<std::shared_ptr<Var>> LocalVars;     // 函数所有参数
    std::list<std::shared_ptr<AstNode>> Statms;

    FunctionNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class FuncCallNode: public AstNode {
public:
    std::string_view FuncName;
    std::vector<std::shared_ptr<AstNode>> Args;

    FuncCallNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class ExprStatmNode: public AstNode {
public:
    std::shared_ptr<AstNode> Lhs{nullptr};

    ExprStatmNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class DeclarationStatmNode: public AstNode {
public:
    std::list<std::shared_ptr<AssignExprNode>> AssignNodes;

    DeclarationStatmNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class IfStatmNode: public AstNode {
public:
    std::shared_ptr<AstNode> Cond{nullptr};
    std::shared_ptr<AstNode> Then{nullptr};
    std::shared_ptr<AstNode> Else{nullptr};

    IfStatmNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class WhileStatmNode: public AstNode {
public:
    std::shared_ptr<AstNode> Cond{nullptr};
    std::shared_ptr<AstNode> Then{nullptr};

    WhileStatmNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class ForStatmNode: public AstNode {
public:
    std::shared_ptr<AstNode> Init{nullptr};
    std::shared_ptr<AstNode> Cond{nullptr};
    std::shared_ptr<AstNode> Inc{nullptr};
    std::shared_ptr<AstNode> Then{nullptr};

    ForStatmNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class ReturnStatmNode: public AstNode {
public:
    std::shared_ptr<AstNode> Lhs;

    ReturnStatmNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class BlockStatmNode: public AstNode {
public:
    std::list<std::shared_ptr<AstNode>> Statms;

    BlockStatmNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class AssignExprNode: public AstNode {
public:
    std::shared_ptr<AstNode> Lhs;
    std::shared_ptr<AstNode> Rhs;

    AssignExprNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

// 二元操作符
enum class BinaryOperator {
    Add, Sub, Mul, Div, PtrAdd, PtrSub, PtrDiff,
    Equal, PipeEqual, Greater, GreaterEqual, Lesser, LesserEqual,
};

// 二元操作符节点
class BinaryAstNode: public AstNode {
public:
    BinaryOperator BinOp;
    std::shared_ptr<AstNode> Lhs;
    std::shared_ptr<AstNode> Rhs;

    BinaryAstNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

enum class UnaryOperator {
    Plus, Minus, Amp, Deref, 
};

class UnaryAstNode: public AstNode {
public:
    UnaryOperator UnaryOp;
    std::shared_ptr<AstNode> Lhs;

    UnaryAstNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

// 常量节点
class ConstantAstNode: public AstNode {
public:
    long Value;

    ConstantAstNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

// sizeof节点
class SizeofNode: public AstNode {
public:
    // SizeofNode(std::shared_ptr<Token> tok) :AstNode(tok) {} 
    std::shared_ptr<AstNode> Lhs{nullptr};

    SizeofNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};

class Var {
public:
    std::shared_ptr<Type> Ty;
    std::string_view Name;
    int Offset;     
};


class VarAstNode:public AstNode {
public:
    std::shared_ptr<Var> VarObj;

    VarAstNode(std::shared_ptr<Token> tok) : AstNode(tok) {}
    void Accept(AstVisitor *visitor) override;
};


#endif // !AST_NODE_H